#include "inc_test.h"

// #define MAX_STACKSIZE	   (8192)
// #define MIN_STACKSIZE	   (512) /* 注意redzone,*/

#define TEST_NR			 (100000)
#define TEST_NESTED_DEPTH   (64)

CROUT_STRUCT *crs[TEST_NR];
void *cofun(void *arg){
	// word_t ret;
	word_t next = (word_t)arg + 1;
	if (next < TEST_NR){
		if ((next % (TEST_NESTED_DEPTH)) != 0){
		// printf("[prompt %ld] ready to create\n", next);
			CROUT_RESUME(crs[next]);
		}
	}
	return (void *)next;
}
void test_nested(){
	CROUT_ATTR test_attr;
	test_attr.share_stack = NULL;
	struct timespec ts;
	struct timespec dt;
	word_t cycles0;
	word_t cycles1;
	TIME_STAMP(&ts);
	for(unsigned long idx = 0; idx < TEST_NR; idx++){
		test_attr.stack_size = __hash64(ts.tv_nsec + idx) % MAX_STACKSIZE + MIN_STACKSIZE;
		if (0 != CROUT_CREATE(&crs[idx], &test_attr, cofun, (void *)(idx))){
			printf("create failed\n");
			return;
		}
	}

	TIME_STAMP(&ts);
	cycles0 = rdcnt_relax();
	for(unsigned long test_nr = 0; test_nr < TEST_NR; test_nr += TEST_NESTED_DEPTH){
		CROUT_RESUME(crs[test_nr]);
	}
	// CROUT_RESUME(crs[TEST_NESTED - 1]);
	cycles1 = rdcnt_relax();
	TIME_STAMP(&dt);
	// printf("%lu nested execution to yield time [us] %lu[%ld]\n", (unsigned long)TEST_NESTED, TIME_DELTA_US(&ts, &dt), cycles1-cycles0);
	printf("[%8llu ns/ops] %lu nested(%lu depth) exec time in us: %llu (%lld cycles/op)\n", \
		TIME_DELTA_NS(&ts, &dt)/TEST_NR, (ulong_t)TEST_NR, (unsigned long)TEST_NR, \
		TIME_DELTA_US(&ts, &dt), ((llong_t)cycles1-cycles0)/TEST_NR);
	

	for(unsigned long idx = 0; idx < TEST_NR; idx++){
		CROUT_RELEASE(crs[idx]);
	}
	fprintf(stderr, "%llu\n", TIME_DELTA_US(&ts, &dt));

}
int main(){
	test_nested();
}
